using System;
using System.Collections.Generic;
using Subsync.Core.Sync;

namespace Subsync.GUI
{
	/// <summary>
	/// Author: Steven Goh Jian Wen
	/// </summary>
    public enum RemoteAdd
    {
        Media,
        Sync,
    }

    public class AddRemoteFolderManager
    {
        //Class Variables
        private string path_to_folder;
        private string new_sync_name;
        private string description;
        private string icon;
        private bool automatic_conflict_management;
        private string repo_url;
        private RemoteAdd method;
        private string media_path;

		private bool has_conflicts = false;
		private bool has_errors = false;
		private string error_description = "";

        //Class Properties
        public bool HasConflicts
        {
            get { return has_conflicts; }
        }

        public bool HasErrors
        {
            get { return has_errors; }
        }

        public string ErrorMsg
        {
            get { return error_description; }
        }

        /// <summary>
        /// Get path of folder to be synced.
        /// </summary>
        public SyncAddError Step1(string path_to_folder)
        {
            if (!Subsync.GUI.Tools.FolderExists(path_to_folder))
            {
                return SyncAddError.FolderDoesNotExist;
            }
            if (Subsync.GUI.Tools.IsVersioned(path_to_folder))
            {
                return SyncAddError.WorkingCopyPathError;
            }
            if (Subsync.GUI.Tools.IsInsideAnotherWorkingCopy(path_to_folder))
            {
                return SyncAddError.WorkingCopyPathError;
            }
            this.path_to_folder = path_to_folder;
            return SyncAddError.Ok;
        }

        /// <summary>
        /// Method of local sync
        /// </summary>
        /// <param name="method">
        /// A <see cref="LocalAdd"/>
        /// </param>
        /// <param name="sync_name">
        /// A <see cref="System.String"/>
        /// </param>
        /// <param name="media_path">
        /// A <see cref="System.String"/>
        /// </param>
        public SyncAddError Step2(RemoteAdd method, string media_path)
        {
            if (method == RemoteAdd.Media)
            {
                //check that it is a repo
                if (!Subsync.GUI.Tools.IsRemoteRepo(media_path))
                    return SyncAddError.NotRepo;
                this.media_path = media_path;
                this.repo_url = this.media_path.Replace(System.IO.Path.DirectorySeparatorChar, '/');
            }
            this.method = method;
            return SyncAddError.Ok;
        }

        /// <summary>
        /// Get new sync name
        /// </summary>
        /// <param name="new_sync_name">
        /// A <see cref="System.String"/>
        /// </param>
        public SyncAddError Step3(string new_sync_name)
        {
            if (Subsync.GUI.Tools.SyncExists(new_sync_name))
                return SyncAddError.SyncNameExists;
            if (new_sync_name.Trim() == "")
                return SyncAddError.EmptyString;
            this.new_sync_name = new_sync_name;
            return SyncAddError.Ok;
        }

        /// <summary>
        /// Sync description
        /// </summary>
        /// <param name="desc">
        /// A <see cref="System.String"/>
        /// </param>
        public SyncAddError Step4(string desc)
        {
            this.description = desc;
            return SyncAddError.Ok;
        }

        /// <summary>
        /// Get conflict management option
        /// </summary>
        /// <param name="cm">
        /// A <see cref="System.Boolean"/>
        /// </param>
        public SyncAddError Step5(bool conflict_m)
        {
            this.automatic_conflict_management = conflict_m;
            return SyncAddError.Ok;
        }

        /// <summary>
        /// Get Icon Path
        /// </summary>
        /// <param name="icon_path">
        /// A <see cref="System.String"/>
        /// </param>
        public SyncAddError Step6(string icon_path)
        {
            if (System.IO.File.Exists(icon_path))
                this.icon = icon_path;
            return SyncAddError.Ok;
        }

        public void Execute ()
        {
        	Sync sync = new Sync ();

            sync.GuiConflict += HandleSGuiConflict;
        	sync.gui = true;
        	sync.icon = this.icon;
        	sync.description = this.description;

			try {
        		sync.AddSync (SyncType.Network, "", this.new_sync_name, this.path_to_folder, this.repo_url, this.automatic_conflict_management);
        	}
			catch (SyncNotFound) {
				this.has_errors = true;
				this.error_description = "Sync not found.";
			}
			catch (FolderDoesNotExist) {
				this.has_errors = true;
				this.error_description = "Folder does not exist.";
			}
			catch (RepositoryNotFound) {
				this.has_errors = true;
				this.error_description = "Repository cannot be found.";
			}
			catch (SyncNameConflict) {
				this.has_errors = true;
				this.error_description = "Sync name conflicts.";
			}
			catch (PathAlreadyAWorkingCopy) {
				this.has_errors = true;
				this.error_description = "Directory is a SVN working copy, cannot proceed.";
			} catch (DiskSpaceException) {
				this.has_errors = true;
				this.error_description = "Disk is full, please clear some space and try again.";
			}
			catch (Exception) {
				this.has_errors = true;
				this.error_description = "An unknown error has occurred.";
			}

        }

        void HandleSGuiConflict (object source, Sync sync)
        {
        	this.has_conflicts = true;
        	ConflictDialog conflict = new ConflictDialog (sync, false);
        	conflict.Show ();
        }
    }
}
